<template>
  <div class="fx-checkbox"
       :class="{active:handleActive,disabled:handleDisabled}"
       @click="checkboxClick">
    <div class="fx-checkbox-select-box">
      <input type="checkbox" hidden :name="isChecked">
      <slot name="icon">
        <i v-if="!indeterminate" class="icon iconfont icon-check fs10"/>
        <em v-else class="indeterminate" :class="{active:indeterminate}"></em>
      </slot>
    </div>
    <div class="fx-checkbox-label">
      <slot>{{ label }}</slot>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, inject, onMounted, PropType, Ref, ref, SetupContext } from 'vue'
import { Emitter } from 'mitt'
import { useModelWatch } from '@/base/hooks'
import { ModelValue } from '@/base/checkbox/checkboxGroup.vue'

interface CheckboxProps {
  modelValue: boolean;
  disabled: boolean;
  label: ModelValue;
  indeterminate: boolean;
}

export default defineComponent({
  name: 'FCheckbox',
  props: {
    // v-model
    modelValue: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 禁用
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 选项
    label: {
      type: [String, Object] as PropType<ModelValue>,
      default: ''
    },
    // 半选样式
    indeterminate: {
      type: Boolean as PropType<boolean>,
      default: false
    }
  },
  emits: ['update:modelValue', 'change'],
  setup (props: CheckboxProps, ctx: SetupContext) {
    // 是否选中
    const isChecked = ref<boolean>(props.modelValue)
    // 获取当前 checkboxGroup 选中数据集
    const checkboxGroupValue = inject<Ref<Array<ModelValue>> | undefined>('checkboxGroupValue', undefined)
    // 获取当前 checkboxGroup 禁用
    const checkboxGroupDisabled = inject<boolean>('checkboxGroupDisabled', false)
    // 获取当前 checkboxGroup 对象选择key
    const checkboxGroupValueKey = inject<string>('checkboxGroupValueKey', '')
    // 获取当前 checkboxGroup 选中个数限制
    type CheckboxNumberProps = { max: number, min: number } | undefined
    const checkboxGroupNumber = inject<CheckboxNumberProps>('checkboxGroupNumber', undefined)
    // 获取checkboxGroup 传数据
    const checkboxGroupMittEmit = inject<Emitter['emit'] | undefined>('checkboxGroupMittEmit', undefined)
    // 接收formItem mitt 监听器
    const formItemMitt = inject<Emitter['emit'] | undefined>('formItemMitt', undefined)

    // 处理选中样式
    const handleActive = computed(() => {
      // 当不存在父组件时 直接使用自身选中状态
      if (!checkboxGroupMittEmit) return isChecked.value
      if (!checkboxGroupValue) return false
      // 根据选中的数组 显示选中状态
      return checkboxGroupValue.value.some((item: ModelValue) => {
        if (typeof item === 'string' && typeof props.label === 'string') return item === props.label
        if (typeof item === 'object' && typeof props.label === 'object' && checkboxGroupValueKey) {
          return item[checkboxGroupValueKey] === props.label[checkboxGroupValueKey]
        }
      })
    })
    // 处理禁用样式
    const handleDisabled = computed((): boolean => {
      // 禁用状态
      let isMaxMin = false
      const arr = checkboxGroupValue?.value
      // 如果存在父组件的列表数据  并且存在选中个数限制
      if (arr && arr.length && checkboxGroupNumber) {
        isMaxMin = arr.length >= checkboxGroupNumber.max || arr.length < checkboxGroupNumber.min
        // 将非选中状态显示可点状态
        isMaxMin = isMaxMin && !handleActive.value
      }
      return checkboxGroupDisabled || props.disabled || isMaxMin
    })
    // 多选框点击
    const checkboxClick = (): void => {
      if (props.disabled || checkboxGroupDisabled || handleDisabled.value) return
      if (checkboxGroupMittEmit && checkboxGroupValue?.value) {
        checkboxGroupMittEmit('checkboxMitt', props.label)
      } else {
        isChecked.value = !isChecked.value
        if (formItemMitt) formItemMitt('formItemValue', isChecked.value)
      }
      ctx.emit('change', isChecked.value)
    }
    // 数据双向绑定hook
    useModelWatch<boolean>(() => props.modelValue, isChecked, ['update:modelValue'])

    onMounted(() => {
      if (formItemMitt) formItemMitt('formItemValue', isChecked.value)
    })

    return {
      isChecked,
      checkboxGroupValue,
      checkboxGroupDisabled,
      handleActive,
      handleDisabled,
      checkboxClick
    }
  }
})
</script>
